module utils.SecurityVerification;

import vibe.http.server : HTTPServerRequest, HTTPServerResponse, HTTPMethod;
import utils.RespData : RespData;

/** 
* 时间戳验证
*/
void timeStampValidator (HTTPServerRequest req, HTTPServerResponse resp)
{
    import std.conv : to;
    import std.datetime.systime : Clock;
    import vibe.data.json : Json;

    auto reqMethod = req.method;
    if (reqMethod == HTTPMethod.GET || reqMethod == HTTPMethod.DELETE)
    {
        string timeStampStr = req.query.get("time", "");
        // 查询参数中没有time字段或无值
        if (timeStampStr == "")
        {
            resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
            return;
        }
        else // 有time字段
        {
            long timeStamp = to!long(timeStampStr);
            long now = Clock.currTime.toUnixTime();
            if (now - timeStamp > 300)
            {
                resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
                return;
            }
        }
    }

    if (reqMethod == HTTPMethod.POST || reqMethod == HTTPMethod.PUT)
    {
        Json json = req.json;
        // json中没有time字段
        if (json.length == 0 || json["time"].type == Json.Type.undefined)
        {
            resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
            return;
        }
        else // json中有time字段
        {
            long time = json["time"].to!long();
            long now = Clock.currTime.toUnixTime();
            if (now - time > 300)
            {
                resp.writeJsonBody(RespData.newData(400, "错误的请求"), 400);
                return;
            }
        }
    }

}

/** 
 * 请求参数签名验证函数
 * Params:
 *   reqParamsStr = 请求参数字符串
 *   sign = 签名
 * Returns: 签名是否有效
 */
bool signValidator (string reqParamsStr, string sign)
{
    import std.digest : toHexString, Order, LetterCase;
    import std.digest.sha : sha256Of;
    import utils.ConstValue : Const;

    if (reqParamsStr.length == 0 || sign is null || sign.length == 0)
    {
        return false;
    }

    ubyte[] sha256Bytes = sha256Of((reqParamsStr ~ Const.signSecretStr));
    string encodedParamsStr = toHexString!(Order.increasing, LetterCase.lower)(sha256Bytes);
    string encodedSign = encodedParamsStr[0 .. 15];
    if (sign == encodedSign)
    {
        return true;
    }

    return false;
}
